package com.ceba.test.modules.cnca;

import com.alibaba.fastjson.JSON;
import com.ceba.base.exception.IDSException;
import com.ceba.test.base.config.LogicPathUtil;
import com.ceba.test.base.configs.CebaConfig;
import com.ceba.test.base.enums.CncaReturnCodeEnum;
import com.ceba.test.modules.storage.logicService.StorageFileCacheManage;
//import com.csvreader.CsvReader;
//import com.csvreader.CsvWriter;
import com.httpclient.HttpClientUtil;
import com.httpclient.common.HttpConfig;
import com.httpclient.exception.HttpProcessException;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;

/**
 * 上传检测报告到直报系统
 * Created by liguangyao on 3/8/2020.
 */
public class CncaLogicService {
    private static Logger logger = LoggerFactory.getLogger(CncaLogicService.class);

    public static String CNCA_TEMPLATE_FILE_NAME = "cnca-report-template.csv";
    private static String CSV_CHARSET = "utf-8";

    /**
     * 创建上传检测报告到直报系统的文件模板
     */
    public boolean createCncaTemplateCsv() {
        String templateDir =  LogicPathUtil.getPhysicalTemplateFolder(StorageFileCacheManage.getSystemUseAddressId());
        String templateFilePath = templateDir + CNCA_TEMPLATE_FILE_NAME;
        CsvWriter csvWriter = null;
        try {
            File csvFile = new File(templateFilePath);
            if (csvFile.exists()) {
                return true;
            }
            // 创建CSV写对象
            csvWriter = new CsvWriter(templateFilePath,',', Charset.forName(CSV_CHARSET), true);
            // 写表头
            String[] headers = {"报告编号","报告生成年份"};
            csvWriter.writeRecord(headers);

            return true;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (null != csvWriter) {
                csvWriter.close();
            }
        }

        return false;
    }

    public UploadReportRequest readCncaCsv(String filePath) {
        CsvReader csvReader = null;
        List<CncaTestOrg> cncaTestOrgs = new ArrayList<>();
        UploadReportRequest uploadReportRequest = new UploadReportRequest();
        int lineNum = 1;
        List<Integer> wrongLines = new ArrayList<>();

        try {
            // 创建CSV读对象
            csvReader = new CsvReader(filePath, ',', Charset.forName(CSV_CHARSET));
            // 读表头
            csvReader.readHeaders();

            while (csvReader.readRecord()){
                ++lineNum;
                // 读一整行
                System.out.println(csvReader.getRawRecord());

                String certNumber = csvReader.get(0);
                String reportYear = csvReader.get(1);
                if (StringUtils.isEmpty(certNumber) || StringUtils.isEmpty(reportYear)) {
                    //记录所有错误数据，一次返回给用户
                    wrongLines.add(lineNum);
                    continue;
                }

                CncaTestReport cncaTestReport = new CncaTestReport();
                cncaTestReport.setOrgName(CebaConfig.CNCA_ORG_NAME);
                cncaTestReport.setCertiNumber(certNumber);
                cncaTestReport.setReportYear(reportYear);

                CncaTestOrg cncaTestOrg = new CncaTestOrg();
                cncaTestOrg.setList(cncaTestReport);
                cncaTestOrg.setOrgCode(CebaConfig.CNCA_ORG_CODE);
                cncaTestOrgs.add(cncaTestOrg);
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new IDSException("报告《" + filePath + "》读取解析失败。请检查是否合法的csv文件！", e);
        } finally {
            if (null != csvReader) {
                csvReader.close();
            }
        }

        if(!wrongLines.isEmpty()) {
            StringBuilder sb = new StringBuilder();
            sb.append("第");
            for (Integer wrongLineNum : wrongLines) {
                sb.append(wrongLineNum);
                sb.append("、");
            }
            sb.append("行");
            throw new IDSException("报告《" + filePath + "》中，以下行的数据格式不正确，请检查：" + sb.toString());
        }

        uploadReportRequest.setuId(CebaConfig.CNCA_UID);
        uploadReportRequest.setDataList(cncaTestOrgs);
        uploadReportRequest.setDataCount(cncaTestOrgs.size());

        return uploadReportRequest;
    }

    public boolean uploadReport(String filePath) throws HttpProcessException, NoSuchAlgorithmException {
        String dk = accessKey();
        UploadReportRequest request = readCncaCsv(filePath);
        request.setDk(dk);

        return doUploadReport(request);
    }

    /**
     * 获取直报系统的动态key，调用业务接口时必须将动态key作为参数之一传给服务平台。动态key有效时长为10分钟，使用一次后即失效。
     * @return 返回动态key
     */
    private String accessKey() throws NoSuchAlgorithmException, HttpProcessException {
//        //TODO 测试代码，后面要去掉
//        if (true) {
//            return "dk001";
//        }

        String md5Password = MessageDigest.getInstance("md5").digest(CebaConfig.CNCA_PASSWORD.getBytes()).toString();
        AccessKeyRequest request = new AccessKeyRequest(CebaConfig.CNCA_UID, CebaConfig.CNCA_USERNAME, md5Password);

        String httpBody = JSON.toJSONString(request);
        HttpConfig config = HttpConfig.custom()
                            .url(CebaConfig.CNCA_URL)				//设置请求的url
                            .encoding("utf-8") 			//设置请求和返回编码，默认就是Charset.defaultCharset()
                            .json(httpBody)			    //json方式请求的话，就不用设置map方法，当然二者可以共用。
                            ;

        logger.info("获取cnca的动态key。http request：" + httpBody);
        String result = HttpClientUtil.post(config);	//post请求
        logger.info("获取cnca的动态key。http response：" + result);
        AccessKeyResponse response = JSON.parseObject(result, AccessKeyResponse.class);
        if (!response.getRenCode().equals(CncaReturnCodeEnum.CODE_0000.getCode())) {
            throw new IDSException(response.getRenCode() + ":" + response.getRenDesc());
        }
        return response.getData();
    }

    private boolean doUploadReport(UploadReportRequest reportRequest) throws HttpProcessException {
        String httpBody = JSON.toJSONString(reportRequest);
        HttpConfig config = HttpConfig.custom()
                .url(CebaConfig.CNCA_URL)				//设置请求的url
                .encoding("utf-8") 			//设置请求和返回编码，默认就是Charset.defaultCharset()
                .json(httpBody)			    //json方式请求的话，就不用设置map方法，当然二者可以共用。
                ;

        logger.info("上传报告到cnca。http request：" + httpBody);
        String result = HttpClientUtil.post(config);	//post请求
        logger.info("上传报告到cnca。http response：" + result);
        UploadReportResponse response = JSON.parseObject(result, UploadReportResponse.class);
        if (response.getRenCode().equals(CncaReturnCodeEnum.CODE_1000.getCode())) {
            return true;
        } else if (response.getRenCode().equals(CncaReturnCodeEnum.CODE_1001.getCode())) {
            logger.error("上传报告到直报系统，部分数据失败：");
            logger.error(response.getFailListString(CncaFailList.MAX_FAIL_COUNT));
            throw new IDSException(response.getFailListString(10));
        } else {
            throw new IDSException(response.getRenCode() + ":" + response.getRenDesc());
        }
    }

    public static void main(String[] args) {
        String testFilePath = "F:\\ceba\\be-nexus\\ep-web\\src\\main\\webapp\\upfile\\template\\testCsv.csv";
        File csvFile = new File(testFilePath);

        if (csvFile.exists()) {
//            csvFile.delete();
            System.out.println("文件已经存在！删除后再测试，或者换一个测试文件。");
//            return;
        }
        try {
            testWriteCsv(testFilePath);
            testReadCsv(testFilePath);
        } catch (IOException e) {
            e.printStackTrace();
        }

//        csvFile.delete();
    }

    protected static void testWriteCsv(String csvFilePath) throws IOException {
        CsvWriter csvWriter = new CsvWriter(csvFilePath,',', Charset.forName(CSV_CHARSET), true);
        // 写表头
        String[] headers = {"报告编号","报告生成年份"};
        csvWriter.writeRecord(headers);
        //写入一行内容
        addOneLine(csvWriter, new String[]{"F115","2020"});
        addOneLine(csvWriter, new String[]{"中文测试","2020"});
        addOneLine(csvWriter, new String[]{"  测试 前后空格"," 2020 "});              //读取csv时去掉空格
        addOneLine(csvWriter, new String[]{"测试内容中的,逗号","2020"});
        addOneLine(csvWriter, new String[]{"\"  \"测试内容中前后的空格","2020"});     //读取csv时保留空格
        addOneLine(csvWriter, new String[]{"测试内容中的\"双引号","2020"});
        csvWriter.close();
    }

    private static void addOneLine(CsvWriter csvWriter, String[] oneLine) throws IOException {
        csvWriter.writeRecord(oneLine);
    }

    protected static void testReadCsv(String csvFilePath) throws IOException {
        CsvReader csvReader = new CsvReader(csvFilePath, ',', Charset.forName(CSV_CHARSET));

        // 读表头
        csvReader.readHeaders();
        while (csvReader.readRecord()){
            // 读一整行
            System.out.println(csvReader.getRawRecord());
            // 读这行的第一列
            System.out.print(csvReader.get(0));
            System.out.print(",");
            // 读这行的第二列
            System.out.print(csvReader.get(1));
            System.out.println("");
        }
        csvReader.close();
    }
}
